﻿; (function (global) {

    'use strict';

    // (x wing rows)
    //--54--6-2--6-2-15-293561784-523-48--3-12-64-5----5732--3--4256--24--59--5-7--924-

    global.Strategies = global.Strategies || {};

    Strategies.Burma = function Burma() {
        this.type = 'elimination';
    }

    Strategies.Burma.prototype.perform = function (grid) {
        var result = this.performByRows(grid);
        if (result)
            return result;

        result = this.performByColumns(grid);
        if (result)
            return result;

        return null;
    }

    Strategies.Burma.prototype.performByRows = function (grid) {
        return this.performOnUnitGroups(grid.cells, grid.cellsByColumn, this.getColumnIndex);
    }

    Strategies.Burma.prototype.performByColumns = function (grid) {
        return this.performOnUnitGroups(grid.cellsByColumn, grid.cells, this.getRowIndex);
    }

    Strategies.Burma.prototype.performOnUnitGroups = function (unitGroups, oppositeUnitGroups, getOppositeIndexFunc) {

        var setOfJ = new LazyValuesSet();
        var containingCells = [];

        for (var k = 1; k < 10; k++) {

            var rowsOfK = this.getRangesContainingCandidate(k, unitGroups);
            var rowsLength = rowsOfK.length;
            if (rowsLength < 2)
                continue;

            for (var c = 2; c < 5; c++) {

                if (rowsLength < c)
                    continue;

                var combinations = CombinationGenerator.getArray(c, rowsLength);
                for (var comb = 0; comb < combinations.length; comb++) {
                    var combination = combinations[comb];
                    var discardCombination = false;
                    setOfJ.clear();

                    for (var rowOfKIndex = 0; rowOfKIndex < c; rowOfKIndex++) {
                        var rowOfK = rowsOfK[combination[rowOfKIndex]];
                        if (rowOfK.count > c) {
                            discardCombination = true;
                            break;
                        }

                        for (var cellIndex = 0; cellIndex < rowOfK.count; cellIndex++) {
                            var cell = rowOfK.cells[cellIndex];

                            if (setOfJ.add(getOppositeIndexFunc(cell))) {
                                if (setOfJ.count > c) {
                                    discardCombination = true;
                                    break;
                                }
                            }

                        }

                        if (discardCombination)
                            break;

                    }

                    if (!discardCombination && setOfJ.count == c) {
                        var keepCells = [];
                        for (var rowOfKIndex = 0; rowOfKIndex < c; rowOfKIndex++) {
                            keepCells.pushArray(rowsOfK[combination[rowOfKIndex]].cells);
                        }

                        var removeCells = [];
                        var colValues = setOfJ.getValues();
                        for (var colIter = 0; colIter < setOfJ.count; colIter++) {
                            removeCells.pushArray(oppositeUnitGroups[colValues[colIter]]);
                        }

                        var result = SolvingHelper.removeFromOtherCells(k, keepCells, removeCells)
                        if (result) {
                            return { candidate: k, containingCells: keepCells, targetCells: removeCells, burmaSize: c };
                        }

                    }

                }
            }
        }

        return null;
    }


    Strategies.Burma.prototype.getColumnIndex = function (cell) {
        return cell.indices.j
    };

    Strategies.Burma.prototype.getRowIndex = function (cell) {
        return cell.indices.i
    };

    Strategies.Burma.prototype.getRangesContainingCandidate = function (k, alignedCellsByIndex) {

        // put only cells containg k ? :)
        var ranges = [];
        for (var i = 0; i < alignedCellsByIndex.length; i++) {
            var cells = alignedCellsByIndex[i];
            var cellsOfK = [];
            var count = 0;
            for (var j = 0; j < 9; j++) {
                if (cells[j].candidates.has[k]) {
                    cellsOfK.push(cells[j]);
                    count++;
                }
            }
            if (count > 0)
                ranges.push({ cells: cellsOfK, count: count });
        }
        return ranges;
    }

}(this));
